Generative Adversarial Networks (GAN)
Table of Contents
Source
If $P_{\text{model}}(x)$ can be estimated as close to $P_{\text{data}}(x)$, then data can be generated by sampling from $P_{\text{model}}(x)$.
In generative modeling, we'd like to train a network that models a distribution, such as a distribution over images.
GANs do not work with any explicit density function !
Instead, take game-theoretic approach
One way to judge the quality of the model is to sample from it.
Model to produce samples which are indistinguishable from the real data, as judged by a discriminator network whose job is to tell real from fake
$$\text{loss} = -y \log h(x) - (1-y) \log (1-h(x))$$
Step 1: Fix $G$ and perform a gradient step to
Step 2: Fix $D$ and perform a gradient step to
$$\max_{G} E_{x \sim p_{z}(z)}\left[\log D(G(z))\right]$$
OR
Step 1: Fix $G$ and perform a gradient step to
$$\min_{D} E_{x \sim p_{\text{data}}(x)}\left[-\log D(x)\right] + E_{x \sim p_{z}(z)}\left[-\log (1-D(G(z)))\right]$$
Step 2: Fix $D$ and perform a gradient step to
$$\min_{G} E_{x \sim p_{z}(z)}\left[-\log D(G(z))\right]$$
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)
n_D_input = 28*28
n_D_hidden = 256
n_D_output = 1
n_G_input = 100
n_G_hidden = 256
n_G_output = 28*28
weights = {
'G1' : tf.Variable(tf.random_normal([n_G_input, n_G_hidden], stddev = 0.01)),
'G2' : tf.Variable(tf.random_normal([n_G_hidden, n_G_output], stddev = 0.01)),
'D1' : tf.Variable(tf.random_normal([n_D_input, n_D_hidden], stddev = 0.01)),
'D2' : tf.Variable(tf.random_normal([n_D_hidden, n_D_output], stddev = 0.01))
}
biases = {
'G1' : tf.Variable(tf.zeros([n_G_hidden])),
'G2' : tf.Variable(tf.zeros([n_G_output])),
'D1' : tf.Variable(tf.zeros([n_D_hidden])),
'D2' : tf.Variable(tf.zeros([n_D_output]))
}
z = tf.placeholder(tf.float32, [None, n_G_input])
x = tf.placeholder(tf.float32, [None, n_D_input])
def generator(G_input, weights, biases):
hidden = tf.nn.relu(tf.matmul(G_input, weights['G1']) + biases['G1'])
output = tf.nn.sigmoid(tf.matmul(hidden, weights['G2']) + biases['G2'])
return output
def discriminator(D_input, weights, biases):
hidden = tf.nn.relu(tf.matmul(D_input, weights['D1']) + biases['D1'])
output = tf.nn.sigmoid(tf.matmul(hidden, weights['D2']) + biases['D2'])
return output
def make_noise(n_batch, n_G_input):
return np.random.normal(size = (n_batch, n_G_input))
G_output = generator(z, weights, biases)
D_fake = discriminator(G_output, weights, biases)
D_real = discriminator(x, weights, biases)
Step 1: Fix $G$ and perform a gradient step to
$$\min_{D} E_{x \sim p_{\text{data}}(x)}\left[-\log D(x)\right] + E_{x \sim p_{z}(z)}\left[-\log (1-D(G(z)))\right]$$Step 2: Fix $D$ and perform a gradient step to
$$\min_{G} E_{x \sim p_{z}(z)}\left[-\log D(G(z))\right]$$D_loss = tf.reduce_mean(- tf.log(D_real) - tf.log(1 - D_fake))
G_loss = tf.reduce_mean(- tf.log(D_fake))
D_var_list = [weights['D1'], biases['D1'], weights['D2'], biases['D2']]
G_var_list = [weights['G1'], biases['G1'], weights['G2'], biases['G2']]
LR = 0.0002
D_optm = tf.train.AdamOptimizer(LR).minimize(D_loss, var_list = D_var_list)
G_optm = tf.train.AdamOptimizer(LR).minimize(G_loss, var_list = G_var_list)
%%time
n_batch = 100
n_iter = 50000
n_prt = 5000
sess = tf.Session()
sess.run(tf.global_variables_initializer())
D_loss_record = []
G_loss_record = []
for epoch in range(n_iter):
train_x, train_y = mnist.train.next_batch(n_batch)
noise = make_noise(n_batch, n_G_input)
# discriminator and generator are separately trained
sess.run(D_optm, feed_dict = {x: train_x, z: noise})
sess.run(G_optm, feed_dict = {z: noise})
if epoch % n_prt == 0:
D_loss_val = sess.run(D_loss, feed_dict = {x: train_x, z: noise})
G_loss_val = sess.run(G_loss, feed_dict = {z: noise})
D_loss_record.append(D_loss_val)
G_loss_record.append(G_loss_val)
print('Epoch:', '%04d' % epoch, 'D_loss: {:.4}'.format(D_loss_val), 'G_loss: {:.4}'.format(G_loss_val))
plt.figure(figsize = (10,5))
plt.subplot(1,2,1)
noise = make_noise(n_batch, n_G_input)
G_img = sess.run(G_output, feed_dict = {z: noise})
plt.imshow(G_img[0,:].reshape(28,28), 'gray')
plt.axis('off')
plt.subplot(1,2,2)
noise = make_noise(n_batch, n_G_input)
G_img = sess.run(G_output, feed_dict = {z: noise})
plt.imshow(G_img[0,:].reshape(28,28), 'gray')
plt.axis('off')
plt.show()
noise = make_noise(n_batch, n_G_input)
G_img = sess.run(G_output, feed_dict = {z: noise})
plt.figure(figsize = (5,5))
plt.imshow(G_img[0,:].reshape(28,28), 'gray')
plt.axis('off')
plt.show()
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
n_D_input = 28*28
n_D_hidden = 256
n_D_output = 1
n_G_input = 128
n_G_hidden = 256
n_G_output = 28*28
n_label = 10 # one-hot-encoding
weights = {
'G1' : tf.Variable(tf.random_normal([n_G_input + n_label, n_G_hidden], stddev = 0.01)),
'G2' : tf.Variable(tf.random_normal([n_G_hidden, n_G_output], stddev = 0.01)),
'D1' : tf.Variable(tf.random_normal([n_D_input + n_label, n_D_hidden], stddev = 0.01)),
'D2' : tf.Variable(tf.random_normal([n_D_hidden, n_D_output], stddev = 0.01))
}
biases = {
'G1' : tf.Variable(tf.zeros([n_G_hidden])),
'G2' : tf.Variable(tf.zeros([n_G_output])),
'D1' : tf.Variable(tf.zeros([n_D_hidden])),
'D2' : tf.Variable(tf.zeros([n_D_output]))
}
z = tf.placeholder(tf.float32, [None, n_G_input])
x = tf.placeholder(tf.float32, [None, n_D_input])
c = tf.placeholder(tf.float32, [None, n_label])
def generator(G_input, label, weights, biases):
hidden = tf.nn.relu(tf.matmul(tf.concat([G_input, label], 1), weights['G1']) + biases['G1'])
output = tf.nn.sigmoid(tf.matmul(hidden, weights['G2']) + biases['G2'])
return output
def discriminator(D_input, label, weights, biases):
hidden = tf.nn.relu(tf.matmul(tf.concat([D_input, label], 1), weights['D1']) + biases['D1'])
output = tf.nn.sigmoid(tf.matmul(hidden, weights['D2']) + biases['D2'])
return output
def make_noise(n_batch, n_G_input):
return np.random.normal(size = (n_batch, n_G_input))
G_output = generator(z, c, weights, biases)
D_fake = discriminator(G_output, c, weights, biases)
D_real = discriminator(x, c, weights, biases)
D_loss = tf.reduce_mean(-tf.log(D_real)-tf.log(1 - D_fake))
G_loss = tf.reduce_mean(-tf.log(D_fake))
D_var_list = [weights['D1'], biases['D1'], weights['D2'], biases['D2']]
G_var_list = [weights['G1'], biases['G1'], weights['G2'], biases['G2']]
LR = 0.0002
D_optm = tf.train.AdamOptimizer(LR).minimize(D_loss, var_list = D_var_list)
G_optm = tf.train.AdamOptimizer(LR).minimize(G_loss, var_list = G_var_list)
%%time
n_batch = 100
n_iter = 50000
n_prt = 5000
sess = tf.Session()
sess.run(tf.global_variables_initializer())
D_loss_record = []
G_loss_record = []
for epoch in range(n_iter):
train_x, train_y = mnist.train.next_batch(n_batch)
noise = make_noise(n_batch, n_G_input)
# discriminator and generator are separately trained
sess.run(D_optm, feed_dict = {x: train_x, z: noise, c: train_y})
sess.run(G_optm, feed_dict = {z: noise, c: train_y})
if epoch % n_prt == 0:
D_loss_val = sess.run(D_loss, feed_dict = {x: train_x, z: noise, c: train_y})
G_loss_val = sess.run(G_loss, feed_dict = {z: noise, c: train_y})
D_loss_record.append(D_loss_val)
G_loss_record.append(G_loss_val)
print('Epoch:', '%04d' % epoch, 'D_loss: {:.4}'.format(D_loss_val), 'G_loss: {:.4}'.format(G_loss_val))
plt.figure(figsize = (5,5))
noise = make_noise(1, n_G_input)
_, train_y = mnist.train.next_batch(1)
G_img = sess.run(G_output, feed_dict = {z: noise, c: train_y})
plt.imshow(G_img.reshape(28,28), 'gray')
plt.axis('off')
plt.show()
Generate fake MNIST images by CGAN
noise = make_noise(1, n_G_input)
G_img = sess.run(G_output, feed_dict = {z: noise, c: [[0,0,0,0,0,1,0,0,0,0]]})
plt.figure(figsize = (5,5))
plt.imshow(G_img.reshape(28,28), 'gray')
plt.axis('off')
plt.show()
Ian Goodfellow, et al., "Generative Adversarial Nets" NIPS, 2014.
At NIPS 2016 by Ian Goodfellow
%%html
<center><iframe src="https://www.youtube.com/embed/9JpdAg6uMXs?rel=0"
width="560" height="315" frameborder="0" allowfullscreen></iframe></center>
%%html
<center><iframe src="https://www.youtube.com/embed/5WoItGTWV54?rel=0"
width="560" height="315" frameborder="0" allowfullscreen></iframe></center>
MIT by Aaron Courville
%%html
<center><iframe src="https://www.youtube.com/embed/JVb54xhEw6Y?rel=0"
width="560" height="315" frameborder="0" allowfullscreen></iframe></center>
Univ. of Wateloo By Ali Ghodsi
%%html
<center><iframe src="https://www.youtube.com/embed/7G4_Y5rsvi8?rel=0"
width="560" height="315" frameborder="0" allowfullscreen></iframe></center>
%%html
<center><iframe src="https://www.youtube.com/embed/odpjk7_tGY0?rel=0"
width="560" height="315" frameborder="0" allowfullscreen></iframe></center>
%%javascript
$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')